package com.qf.homework.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MyBatisUtil {
    //类级别的成员变量 SqlSessionFactory 好处：全局唯一
    private static SqlSessionFactory sqlSessionFactory;

    private static ThreadLocal<SqlSession> threadLocal=new ThreadLocal<>();

    /**
     * 通过静态代码块初始化类级别的成员变量
     * 静态代码快仅在jvm加载class时执行一次
     */
    static {
        try {
            InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
            //创建一个SqlSessionFactoryBuilder对象 创建一个SqlSessionFactory对象
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            //利用SqlSessionFactory 对象可以创建SqlSession对象
             sqlSessionFactory=sqlSessionFactoryBuilder.build(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取SqlSession对象
     * @return
     * @throws IOException
     */
    public static SqlSession getSqlSession()  {
//        //如何创建SqlSession对象
//        //把mybatis-config.xml配置文件转换成流对象
//        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
//        //创建一个SqlSessionFactoryBuilder对象 创建一个SqlSessionFactory对象
//        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//        //利用SqlSessionFactory 对象可以创建SqlSession对象
//        SqlSessionFactory sqlSessionFactory=sqlSessionFactoryBuilder.build(resourceAsStream);
//        // 核心对象 SqlSession
//        SqlSession sqlSession = sqlSessionFactory.openSession();

        //先检查当前线程是否曾经获取过（创建过）SqlSession对象，如果已经过去过，那么直接使用
        SqlSession sqlSession = threadLocal.get();
        if (sqlSession!=null){
            return sqlSession;
        }
        //如果当前线程米有获取过SqlSession对象，那么久创建一个新的SqlSession对象，并且保存起来
        sqlSession =sqlSessionFactory.openSession();
        threadLocal.set(sqlSession);
        return sqlSession;
    }

    /**
     * 提交事务
     */
    public static void commit(){

        //获取当前线程的SqlSession对象
        SqlSession sqlSession = getSqlSession();

        sqlSession.commit();

        //关闭当前线程的sqlSession对象
        closeSqlSession();

    }

    /**
     * 关闭SqlSession
     */
    private static void closeSqlSession() {
        SqlSession sqlSession = getSqlSession();
        threadLocal.remove();
        sqlSession.close();
    }

    /**
     * 回滚实物
     */
    public static void rollBack(){

        //获取当前线程的SqlSession对象
        SqlSession sqlSession = getSqlSession();

        sqlSession.rollback();

        //关闭当前线程的sqlSession对象
        closeSqlSession();
    }

    public static <T> T getMapper(Class<T> clazz){
        SqlSession sqlSession = getSqlSession();
        T mapper = sqlSession.getMapper(clazz);
        return mapper;
    }
}
